package com.mjk.common.core.jdbc.service.plus.provider.interfaces;


import com.mjk.common.base.model.BaseEntity;
import com.mjk.common.core.jdbc.annotation.ArcSharding;
import com.mjk.common.core.jdbc.annotation.Filed;
import com.mjk.common.core.jdbc.annotation.Id;
import com.mjk.common.core.jdbc.service.plus.constns.BeeTypeEntity;
import com.mjk.common.core.jdbc.service.plus.provider.BeeDataSourceType;
import com.mjk.common.core.jdbc.util.TableUtils;
import com.mjk.common.core.jdbc.util.provider.InsertSqlProvider;
import com.mjk.common.core.jdbc.util.provider.SqlProvider;
import com.mjk.common.core.jdbc.util.provider.UpdateSqlProvider;
import com.mjk.common.tools.logger.BizLogger;
import com.mjk.common.util.ClassUtil;
import com.mjk.common.util.ObjectUtils;
import com.mjk.common.util.ReflectionUtils;
import com.mjk.common.util.StrUtils;
import org.springframework.util.CollectionUtils;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public interface IBeeProvider {
    /**
     * 复杂SQL语句
     */
    default String complexSelectByWrapp(Map<String, Object> map){return "";}
    /**
     * 获取建表语句
     */
    default String getCreateTable(BaseEntity entiry) {return "";}

    /**
     * 主键 后缀
     */
    default String getAutoIncrement(boolean primary) {return "";}

    /**
     * 获取表结构
     */
    default String getTableStruct(String tabName) {return "";}

    /**
     * 获取表结构详情 字段 注释
     */
    default String getTableStructDetail(ArcSharding arc) {return "";}

    /**
     * 获取表名称
     */
    String getTabName(ArcSharding arc);

    /**
     * 获取列长度
     */
    String getFiledLenght(String clazz,String length);
    /**
     * 初始化自增主键
     */
    default void initPramaryIncrement(BaseEntity entity) {}

    /**
     * 添加 列
     */
    default String getAlertAdd(boolean isUpdate) {return "";}

    /**
     * 添加 注释
     */
    default String getComment(String comment) {return "";}

    /**
     * 删除列
     */
    default String getAlertDrop(List<String> fieldName) {return "";}

    /**
     * 解析不同字段 返回 字符类型
     * @param condition 条件
     *
     */
    default String trancationField(Object o,String condition) {return "";}

    String countByExample(Map<String, Object> map);

    String deleteByExample(Map<String, Object> map);

    String deleteByPrimaryKey(BaseEntity t);

    String insert(Map<String, Object> map);

    String selectByExample(Map<String, Object> map);

    String selectByPrimaryKey(Map<String, Object> map);

    String updateByPrimaryKeySelective(Map<String, Object> map);

    String updateByExampleSelective(Map<String, Object> map);

    default String deleteBaseList(Map<String, Object> map){
        List list = (List) map.get("list");
        ObjectUtils.isEmpty(list);
        StringBuilder sql = new StringBuilder();
        String tableName = TableUtils.getTableName((BaseEntity) list.get(0));
        sql.append("delete from ").append(tableName).append(" where ");
        List<Field> field = SqlProvider.getValidTableFiled(list.get(0));
        List inStr = new ArrayList();
        //传入的每个bean 里面的条件 都 or
        for (Object object : list) {
            BaseEntity bean = (BaseEntity) object;
            List<String> values = new ArrayList<>();
            for (Field f : field) {
                Object o = ReflectionUtils.getFieldValue(bean, f.getName());
                if (ObjectUtils.isNotEmpty(o)) {
                    if (ClassUtil.isBasicType(o.getClass()) && !(o instanceof String))
                        values.add(f.getName() + "=" + o);
                    else {
                        values.add(f.getName() + "= '" + o + "'");
                    }
                }
            }
            if (!CollectionUtils.isEmpty(values)) {
                inStr.add("(" + StrUtils.join(values, " and ") + ")");
            }
        }
        sql.append(StrUtils.join(inStr," or "));
        return sql.toString();
    }

    default String updateBaseList(Map<String, Object> para){
        List list = (List) para.get("list");
        StrUtils.notNull(list, "list is null");
        String tableName = TableUtils.getTableName((BaseEntity) list.get(0));
        StringBuilder sql = new StringBuilder();
        sql.append("<script>");
        sql.append("update ").append(tableName);
        sql.append(" <trim prefix=\"set\" suffixOverrides=\",\">");
        List<Field> filed = SqlProvider.getValidTableFiled(list.get(0));
        //ArcSharding sharding = list.get(0).getClass().getAnnotation(ArcSharding.class);
        boolean hump = false;

        //获取主键
        List<String> pramary = SqlProvider.getPramaryKeys((BaseEntity) list.get(0));
        for(Field f : filed) {
            Filed bf =  f.getAnnotation(Filed.class);
            String name;
            if(null!=bf) {
                name = ObjectUtils.isEmpty(bf.cloum())?f.getName():bf.cloum();
            }else {
                name = f.getName();
            }
            sql.append("<trim prefix=\"").append(name).append("=case\" suffix=\"ELSE " + name + " end,\">");
            sql.append("<foreach collection=\"list\" item=\"dto\" index=\"index\" >");
            sql.append("  <if test=\"dto.").append(f.getName()).append("!=null\"> ");
            sql.append(" when ").append(getUpdateWhen(pramary, hump, "and")).append(" then #{dto.").append(f.getName()).append("}");
            sql.append("</if>");
            sql.append("</foreach>");
            sql.append("</trim>");
        }
        sql.append(" </trim> ");
        sql.append(" where ");
        sql.append(" <foreach collection=\"list\" separator=\" or \" open=\"(\" close=\")\" item=\"dto\" index=\"index\">");
        sql.append(getUpdateWhen(pramary, hump,"and"));
        sql.append("</foreach>");
        sql.append("</script>");
        return sql.toString();
    }

    default String insertBaseList(Map<String, Object> para){
        List list = (List) para.get("list");
        StrUtils.notNull(list, "list is null");
        String tableName = TableUtils.getTableName((BaseEntity) list.get(0));
        StringBuilder sql = new StringBuilder();
        sql.append("<script>");
        sql.append("insert into ");
        sql.append(tableName);
        sql.append("(").append(InsertSqlProvider.getInsertFiled((BaseEntity) list.get(0), true)).append(")");
        sql.append(" VALUES ");
        sql.append("<foreach collection=\"list\" item=\"item\" index=\"index\" separator=\",\">");
        BaseEntity t = (BaseEntity) list.get(0);
        sql.append("(");
        sql.append(InsertSqlProvider.getInsertFiledValue(t, true));
        sql.append(")");
        sql.append("</foreach>");
        sql.append("</script>");
        return sql.toString();
    }

    default void createSQL(StringBuilder sb, Field field, BeeDataSourceType driverType, boolean isUpdate){
        String fName = SqlProvider.getCloumName(field);
        Filed filed = field.getAnnotation(Filed.class);
        String lenght;
        IBeeProvider handler = driverType.getHandlerInstance();
        IBeeTypeMapping mapping =(IBeeTypeMapping)handler;
        String commentStr=ObjectUtils.isNotEmpty(filed)?filed.comment():"";
        String returnType = ClassUtil.getSimpleName(field.getGenericType().toString());

        boolean pramaryKey = (field.getAnnotation(Id.class) != null);
        BeeTypeEntity typeEntity = mapping.getTypeByJavaType(returnType);
        if (pramaryKey) {
            lenght = filed != null && filed.lenght() > 0 ? filed.lenght() + "" : typeEntity.getLenght();
            sb.append(fName).append(" ").append(typeEntity.getJdbcTypeName())
                    .append(handler.getFiledLenght(returnType, lenght)).append(handler.getAutoIncrement(true)).append(handler.getComment(commentStr)).append(handler.getAlertAdd(isUpdate));
        } else {
            // 兼容枚举类型
            try {
                if (Class.forName(returnType).isEnum()) {
                    returnType = Enum.class.getName();
                }
            } catch (Exception e) {
                BizLogger.error(e);
            }
            if(filed==null) {
                lenght = typeEntity.getLenght();
            }else {
                if(filed.lenght()>0)
                    lenght=filed.lenght()+"";
                else
                    lenght = typeEntity.getLenght();
            }
            // 不在基本配置里面，可以是model中包含了其他model
            String javaType = typeEntity.getJdbcTypeName();//mapping.getJdbcTypeNameByJavaType(returnType, false);
            if (ObjectUtils.isNotEmpty(javaType)) {
                sb.append(fName).append(" ").append(javaType).append(handler.getFiledLenght(returnType, lenght)).append(handler.getAutoIncrement(false)).append(handler.getComment(commentStr)).append(handler.getAlertAdd(isUpdate));
            } else {
                try {
                    Class<?> clazz;
                    if (returnType.contains("class")) {
                        clazz = Class.forName(returnType.substring(6));
                    } else {
                        clazz = Class.forName(returnType);
                    }
                    clazz.newInstance();
                    List<Field> fields = SqlProvider.getValidTableFiled(clazz.newInstance());
                    boolean havingId = false;
                    for (Field f : fields) {
                        Id id = f.getAnnotation(Id.class);
                        if (null != id) {
                            havingId = true;
                            String type = f.getGenericType().toString();
                            sb.append(fName).append("_id ").append(mapping.getTypeByJavaType(type).getJdbcTypeName()).append("(").append(mapping.getTypeByJavaType(type).getLenght()).append(")").append(handler.getAlertAdd(isUpdate));
                        }
                    }
                    // 如果没有配置@ID，就默认LONG类型
                    if (!havingId) {
                        sb.append(fName).append("_id bigint (20").append(")").append(handler.getAlertAdd(isUpdate));
                    }
                } catch (Exception e) {
                    BizLogger.error(e);
                }
            }
        }
    }

    default String buildFiledSql(BaseEntity o,BeeDataSourceType type){
        List<Field> fields = SqlProvider.getValidTableFiled(o);
        StringBuilder sb = new StringBuilder();
        for (Field f : fields) {
            createSQL(sb, f,type,false);
        }
        if (sb.toString().endsWith(",")) {
            return sb.substring(0, sb.toString().length() - 1);
        }
        return sb.toString();
    }

    default String getUpdateWhen(List<String> pramarys,boolean hump,String separator) {
        List<String> result = new ArrayList<>();
        if(CollectionUtils.isEmpty(pramarys)) {
            return "";
        }
        for(String pramary : pramarys) {
            result.add( " "+pramary +"=" + "#{dto."+pramary+"} ");
        }
        return StrUtils.join(result, separator);
    }
}
